let _vue
class VueRouter {
  static install(Vue, options) {
    if (VueRouter.install.installed) {
      return
    } console.dir(VueRouter, '--ssss---')
    VueRouter.install.installed = true
    _vue = Vue
    _vue.mixin({
      beforeCreate() {
        // 获取组件的属性名称
        if (this.$options && this.$options.router) { // 说明这是根组件
          _vue.prototype.$router = this.$options.router
        }
      }
    })
  }
  constructor(options) {
    this.mode = options.mode || 'hash'
    this.routes = options.routes || []
    // 你传递的路由表是一个数组，改造成一个对象：key是路径，value是路径对应的组件{'/home':Home,'/about':About}
    this.routesMap = this.createMap(this.routes)
    // 路由中需要存放当前的路径,当前路径变化的时候，应该渲染对应的组建
    // this.history = {current:null};// 默认是null  当然，我们最好用一个类来管理当前路径，这样方便拓展
    this.data = _vue.observable({
      current: '/'
    })

    this.init() // 开始初始化操作
    this.initComponent(_vue)
  }

  init() {
    // 判断是什么模式,如果是hash应该怎么样，如果是history应该怎么样
    // 如果是hash
    if (this.mode === 'hash') {
      // 先判断用户打开时有没有hash，没有就跳转到#/这样的路径
      location.hash ? '' : location.hash = '/'
      // 读取当前的路径，比如是/home，存到this.history中
      // 刚加载页面的时候，把路径放到this.history中
      window.addEventListener('load', () => {
        this.data.current = location.hash.slice(1)
      })
      // 当路由改变的时候，也要将路径存放到this.history中
      window.addEventListener('hashchange', () => {
        this.data.current = location.hash.slice(1)
      })
    } else { // 如果是history
      // 先判断用户打开的时候有没有路径，没有的恶化就跳转到#/这样的路径
      location.pathname ? '' : location.path = '/'
      // 页面一加载就把路径放到this.histroy中，这个跟hash是一样的,唯一区别的是用pathname，不是hash而已
      window.addEventListener('load', () => {
        this.data.current = location.pathname
      })
      // 当浏览器前进后退的时候，要将对应的路径放到this.history中
      window.addEventListener('popstate', () => {
        this.data.current = location.pathname
      })
    }
  }

  initComponent(Vue) {
    Vue.component('router-link', {
      props: {
        to: String,
        tag: String
      },
      methods: {
        handleClick(e) {
          const mode = this.$root.$root.$options.router.mode
          console.log(this, mode)
          if (mode === 'hash') {
            location.hash = this.to
          } else {
            history.pushState({}, '', this.to)
            // console.log(this.$router)
            this.$router.data.current = this.to
          }
          e.preventDefault()
          return false
        }
      },
      render(h) { // 这个h是createElement
        // 这里的this是什么？在render方法中，this是Proxy，如果你要拿到Vue实例(组件)，那么就要用this._self
        // 要先取到模式，然后根据模式来对应返回
        console.log(this._self, 'this._selfthis._self')
        const mode = this._self.$root.$root.$options.router.mode
        const tag = this.tag ? this.tag : 'a'
        return <tag on-click={this.handleClick} href={mode === 'hash' ? `#${this.to}` : this.to}>{this.$slots.default}</tag>
      }
    })
    const self = this

    Vue.component('router-view', { // 根据当前的状态 current 路由表{'/about':About}
      render(h) {
        // 这里的this是什么？在render方法中，this是Proxy，如果你要拿到Vue实例(根组件)，那么就要用this._self
        // 如何将current 做成动态的，current变化，对应的组件也应该跟着变化
        // vue实现双向绑定 ，主要靠Object.defineProperty的get和set

        const current = self.data.current
        const routeMap = self.routesMap
        return h(routeMap[current])
      }
    })
  }
  createMap(routes) {
    return routes.reduce((prev, next, index, arr) => {
      prev[next.path] = next.component
      return prev
    }, {})
  }
}

export default VueRouter
